package msg.model;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import msg.udp.UDPServer;


/** Server class application */
public class AppServer {

	private Mediator mediator;
	private UDPServer udpServer;
	private List<String> allUsers;
	private String message;

	private String serverSep;
	private String serverIp;
	private int serverPort;
	private boolean serverFlag;

	private String userName;
	private String userTo;
	private String userIp;
	private int userPort;


	/** base constructor */
	public AppServer() {
		this.mediator = new MediatorImpl();
		this.allUsers = new ArrayList<String>();
		this.message = "";
		
		this.serverIp = this.getLocalIP();
		this.serverPort = 54540;
		this.serverSep = "`";
		this.serverFlag = false;

		this.userName = "";
		this.userTo = "";
		this.userIp = "";
		this.userPort = 0;
	}


	/** method run server application */
	public void run() {
		this.udpServer = new UDPServer(this.serverIp, this.serverPort);
		this.serverFlag = this.udpServer.getFlag();
		
		this.serverInfo("Server start!");
		this.serverInfo("IP address: " + this.serverIp + "\nPort number: " + this.serverPort);
		this.serverInfo("-----------------------------------------\n");

		while (this.serverFlag) {
			String buffer = this.udpServer.receive();
			String tab[] = buffer.split(this.serverSep);

			if (tab.length == 5) {
				this.userIp = tab[0];
				this.userPort = this.stringToInt(tab[1]);
				this.userName = tab[2];
				this.userTo = tab[3];
				this.message = tab[4];

				if (this.userTo.equals("<serv>")) {
					if (this.message.equals("<hi>")) {
						if (!this.allUsers.contains(this.userName)) {
							this.allUsers.add(this.userName);
							this.mediator.register(this);

							this.serverInfo(" +++ New user: " + this.userName);
						}
						else this.serverInfo(" xxx Invalid user name.");
					}
					else if (this.message.equals("<bay>")) {
						if (this.allUsers.contains(this.userName)) {
							this.allUsers.remove(this.userName);
							this.mediator.unRegister(this);

							this.serverInfo(" --- Out user: " + this.userName);
						}
						else this.serverInfo(" xxx Invalid user name.");
					}
				}
				else {
					if (!this.allUsers.isEmpty()) {
						if (this.allUsers.contains(this.userTo)) {
							this.mediator.send(this.userTo, this.userName + " >> " + this.message);

							this.serverInfo(" >>> User: " + this.userName + " send: " + this.message);
						}
						else this.serverInfo(" xxx Unregistered user.");
					}
					else this.serverInfo(" xxx Invalid user list.");
				}
			}
			else this.serverInfo(" xxx Wrong data.");
			this.message = "";
		}
		this.serverInfo("-----------------------------------------\nServer stop.");
	}


	/** method print server info */
	private void serverInfo(String txt) {
		System.out.println(txt);	
	}


	/** method gets system IP address */
	private int stringToInt(String num) {
		try {
			return Integer.parseInt(num);

		} catch (Exception ex) {
			System.err.println("Parsing error!");
			System.err.println("Error message: " + ex.getMessage());
			return 0;
		}
	}


	/** method gets system IP address */
	private String getLocalIP() {
		try {
			return InetAddress.getLocalHost().getHostAddress();

		} catch (Exception ex) {
			System.err.println("IP default error!");
			System.err.println("Error message: " + ex.getMessage());
			return "";
		}
	}


	/** get user name */
	public String getUserName() {
		return userName;
	}


	/** get user IP */
	public String getUserIp() {
		return userIp;
	}


	/** get user port */
	public int getUserPort() {
		return userPort;
	}
}
